﻿/**************************************************************
 *
 * 唯一标识：ad597c0f-3250-4067-890c-51858d5aa2e8
 * 命名空间：Sgr.UPMS.Application.DomainEventHandlers
 * 创建时间：2023/9/6 7:41:48
 * 机器名称：DESKTOP-S0D075D
 * 创建者：antho
 * 电子邮箱：fengqinhua2016@163.com
 * 描述：
 *
 **************************************************************/

using MediatR;
using Sgr.Caching.Services;
using Sgr.Domain.Uow;
using Sgr.UPMS.Events;
using Sgr.UPMS.Domain.Users;

namespace Sgr.UPMS.Application.DomainEventHandlers
{
    public class RoleAuthChangedDomainEventHandle : INotificationHandler<RoleAuthChangedDomainEvent>
    {
        private readonly ICacheManager _cacheManager;
        private readonly IUpmsQueryContext _context;
        private readonly IUnitOfWorkManager _unitOfWorkManager;

        public RoleAuthChangedDomainEventHandle(
            IUnitOfWorkManager unitOfWorkManager,
            IUpmsQueryContext context,
            ICacheManager cacheManager)
        {
            _unitOfWorkManager = unitOfWorkManager ?? throw new ArgumentNullException(nameof(unitOfWorkManager));
            _context = context ?? throw new ArgumentNullException(nameof(context));
            _cacheManager = cacheManager ?? throw new ArgumentNullException(nameof(cacheManager));
        }

        public async Task Handle(RoleAuthChangedDomainEvent notification, CancellationToken cancellationToken)
        {
            async Task clearCacheAsync()
            {
                // 清理所有角色下的用户认证缓存
                var query = _context.QueryWithNavigation<User>("Roles")
                    .Where(u => u.Roles.Any(d => d.RoleId == notification.RoleId))
                    .Select(u => new { UserId = u.Id, u.OrgId });

                var users = await _context.ToListAsync(query, cancellationToken);

                const int batchSize = 50;
                var keys = users
                    .Select(item => CacheKeys.GetUserPermissionKey(item.OrgId, item.UserId)) // 匿名类型访问属性
                    .ToList();

                for (int i = 0; i < keys.Count; i += batchSize)
                {
                    var batch = keys.Skip(i).Take(batchSize);
                    await _cacheManager.RemoveAsync(batch, cancellationToken);
                }
            }

            if (_unitOfWorkManager.Current != null && !_unitOfWorkManager.Current.IsCompleted)
                _unitOfWorkManager.Current.AddCompletedHandler(clearCacheAsync);
            else
                await clearCacheAsync();
        }
    }
}